import  math
from ._global import EPSILONE  ## .是从当前的包中 _global中 模块导入 epsilon变量

class Vecotr :
    def __init__(self  ,  lst):
        # 调用构造的时候传入的是一个引用之  ， 如调用处 这个值修改的话，就会影响_values值
        self._values = list(lst)  # 利用list构造函数 ， 相当于复制一份
    @classmethod
    def zero(cls , dim):
        """返回一个dim维的零向量"""
        return cls([0] * dim)
    def norm(self):
        """返回向量的模"""
        return math.sqrt(sum(e ** 2 for e in self))
    def normalize(self):
        """返回向量的单位向量  -  向量中每一个分量除以此向量的模 最终组成返回的单位向量"""
        # return Vecotr([e / self.norm() for e in self])  这样不优  ， 因为重复计算了norm
        # norm提到外面  ， 并且向量创建一个副本  ，ps： 直接用 self 会修改原始向量，而创建副本则不会
        # return 1/self.norm() * Vecotr(self._values)
        # 判断零向量 ， 如果是浮点数 ， 和0进行判断 是不能直接使用 == 的  是因为计算机中 浮点计算很容易产生误差
        #norm 是一个正数 因为它是开跟出来的
        # if self.norm() == 0 :
        if self.norm()  < EPSILONE : # 和一个极小的值作比较
            raise ZeroDivisionError("Normalize error ！  norm is zero ~ ")
        return Vecotr(self._values) / self.norm()
    def dot(self,another):
        """向量点乘 ， 返回结果标量
        两个向量进行点乘 ， 维度必须相等"""
        assert len(self) == len(another),\
            "Error in dot product . Length of vectors must same ."
        return sum(a * b for a , b in zip(self , another))





    def __repr__(self):
        return "Vector({})".format(self._values)
    def __str__(self):
        return "({})".format(", ".join( str(e) for e in self._values))
    def __len__(self):
        """返回向量长度 (有多少个元素)"""
        return len(self._values)
    def __getitem__(self, index):
        """取向量的第index个元素"""
        return self._values[index]
    def  __add__(self, another):
        """"向量加法 ， 返回结果向量"""
        assert len(self) == len(another), \
            "Error in adding  . Length of vectors must be same . "
        # return Vecotr([a + b for a,b in zip(self._values , another._values)])  # 尽量不去访问私有成员变量 _下划线约定
        return Vecotr([a + b for a, b in zip(self, another)])  #可迭代不需要访问 __values
    def __sub__(self, another):
        """向量剑法  ， 返回结果向量"""
        assert  len(self) == len(another), \
            "Error in subtracting . Length of vectors must be same ."
        return Vecotr([a- b for a,b in zip(self , another)])
    def __iter__(self):
        """"返回向量的迭代器"""
        return self._values.__iter__()  # 列表本身就有迭代器
    def __mul__(self, k):
        """返回数量乘法的结果向量 ： self * k"""
        return Vecotr([k * e for e in self])
    def __rmul__(self, k):
        """返回数量乘法的结果向量 ： k * self """
        return self * k
    def __pos__(self):
        """"返回向量取正的结果向量"""
        return 1* self
    def __neg__(self):
        """返回向量取负的结果向量"""
        return -1 * self
    def __truediv__(self, k):
        """返回数量除法的结果向量  -  / // python3 中区分普通的除法、整数除法
        由于实现的向量类中 ， 每一个元素不一定都是整数  所以覆盖 __truediv__ 魔法方法
        这个数量除法本质就是 数量乘法 ， 为了编程方便 ， 造了一个这个概念
        其结果就相当于是  self / k"""
        return (1/k) * self


